package tool.workflow.fsSoft

import akka.stream.Materializer
import command.CommandExec
import dao._
import shared.Pojo._
import tool.Pojo._
import shared.Pojo._
import tool.{FeatureSelectionTool, FormTool, Pojo, Tool, plot}
import tool.workflow.fsSoft.AllFsSoft.FSSoftBT

import java.io.File
import implicits.Implicits._
import play.api.i18n.Messages
import play.api.libs.ws.WSClient
import play.api.mvc.{AnyContent, Request}
import shared.pojo.WorkflowMission.FsData
import shared.tool.DefaultPickle
import tool.plot.ZScore
import tool.soft.DiffAnaSoft
import tool.softT._

import scala.collection.immutable.SeqMap
import upickle.default._

/** Created by yz on 3/12/2020
  */
object FSUniAna extends FSSoftBT with AllSoftBT with UniAnaSoftT {

  override def getFileInfos(workspaceDir: File, index: Int)(implicit
      matrixFileDataDao: MatrixFileDataDao,
      messages: Messages
  ): List[FileInfoData] = {
    val subWorkspaceDir = new File(workspaceDir, s"${nameStr}_${index}")
    val isMul = Tool.isMulGroup(subWorkspaceDir)
    if (isMul) {
      List(
        FileInfoData("AllMet_Test.csv", messages("allMetTest")),
        FileInfoData("Diff_Met_Test.csv", messages("diffMetTest")),
        FileInfoData("AllMet_Boxplot.pdf", messages("allMetBoxplot")),
        FileInfoData("AllMet_Vioplot.pdf", messages("allMetVioplot")),
        FileInfoData("AllMet_Z_Score.csv", messages("allMetZScore")),
        FileInfoData("Z_Score_Plot.pdf", messages("zScorePlot")),
        FileInfoData("Diff_Metabolite.csv", messages("diffMetabolite")),
        FileInfoData("comparisons.csv", "comparisons"),
        FileInfoData("post_hoc.csv", "post hoc")
      )
    } else {
      List(
        FileInfoData("AllMet_Boxplot.pdf", messages("allMetBoxplot")),
        FileInfoData("AllMet_Test.csv", messages("allMetTest")),
        FileInfoData("AllMet_Vioplot.pdf", messages("allMetVioplot")),
        FileInfoData("Volcano_Plot.pdf", messages("volcanoPlot")),
        FileInfoData("Diff_Met_Test.csv", messages("diffMetTest")),
        FileInfoData("AllMet_Z_Score.csv", messages("allMetZScore")),
        FileInfoData("Z_Score_Plot.pdf", messages("zScorePlot")),
        FileInfoData("Diff_Metabolite.csv", messages("diffMetabolite"))
      ).filter { data =>
        new File(subWorkspaceDir, data.fileName).exists()
      }
    }
  }

  def produceSubConfigFile(workspaceDir: File, index: Int, fsData: FsData) = {
    val subConfigFile = new File(workspaceDir, "calculate_config.json")
    DefaultPickle.write(fsData.uniAna(index)).toFile(subConfigFile)
  }

  override def produceInput(workspaceDir: File, resultDir: File, index: Int, parentNodeStr: String, id: String)(implicit
      dao: MyDao,
      messages: Messages
  ): Unit = {
    val groupFile = new File(workspaceDir.getParentFile, "group.txt")
    val fsData = FeatureSelectionTool.getFsData(workspaceDir.getParentFile)
    groupFile.txtLines.lineSeqMap
      .filter { map =>
        fsData.uniAna(index).uniAnaGroups.contains(map("ClassNote"))
      }
      .csvLines
      .toTxtFile(new File(workspaceDir, "group.txt"))
    FeatureSelectionTool.produceSubInputFile(workspaceDir, parentNodeStr)
    produceSubConfigFile(workspaceDir, index, fsData)
  }

  override def resultDeal(workspaceDir: File, resultDir: File, index: Int)(implicit
      ws: WSClient,
      materializer: Materializer,
      messages: Messages
  ): Unit = {
    val commandExec = CommandExec().exec { b =>
      val zScoreCommand =
        if (new File(workspaceDir, "Z_Score_Plot.pdf").exists())
          "convert  -density 300 Z_Score_Plot.pdf  Z_Score_Plot.png"
        else ""
      val command = s"""
                |${zScoreCommand}
                |""".stripMargin
      CommandData(workspace = workspaceDir, commands = List(command), runFileName = "convert.sh")
    }
  }

  override def getCommandData(workspaceDir: File, resultDir: File, index: Int): List[CommandData] = {
    val groupFile = new File(workspaceDir, "group.txt")
    val isMul = Tool.isMulGroup(workspaceDir)
    val solutionFile = new File(Tool.dataDir, "color_solution/color_solution_1.txt")
    val testCommands = if (isMul) {
      val inCommand = s"""
         |${Tool.rScript} ${new File(Tool.rPath, "fs_kw_calculate.R").unixPath}
         |${Tool.rScript} ${new File(Tool.rPath, "mul_group_significant_value_calculate.R").unixPath} --config calculate_config.json
         |${Tool.rScript} ${new File(Tool.rPath, "mul_group_significant_post_hoc_value_calculate.R").unixPath} --config calculate_config.json
         |""".stripMargin
      List(inCommand)
    } else {
      val inCommand = s"""
         |${Tool.rScript} ${new File(Tool.rPath, "volcano_calculate.R").unixPath}
         |${Tool.rScript} ${new File(Tool.rPath, "fill_var_names.R").unixPath}
         |""".stripMargin
      val volcanoPlotCommand = plot.VolcanoPlot.getCommand(workspaceDir.getParentFile, workspaceDir.getName)
      List(inCommand, volcanoPlotCommand)
    }
    val commands = {
      val produceScCommand =
        s"""
           |${Tool.rScript} ${Tool.rPath.unixPath}/produce_sample_color.R --g ${groupFile.unixPath}  --solution ${solutionFile.unixPath}
           |""".stripMargin
      val fillColorCommand =
        s"""
           |${Tool.rScript} ${Tool.rPath.unixPath}/fill_sample_color.R --g ${groupFile.unixPath}  --solution ${solutionFile.unixPath} --pc ${plot.BoxPlot.plotO.configFileName}
           |${Tool.rScript} ${Tool.rPath.unixPath}/fill_sample_color.R --g ${groupFile.unixPath}  --solution ${solutionFile.unixPath} --pc ${plot.ViolinPlot.plotO.configFileName}
           |${Tool.rScript} ${Tool.rPath.unixPath}/fill_sample_color.R --g ${groupFile.unixPath}  --solution ${solutionFile.unixPath} --pc ${plot.ZScore.plotO.configFileName}
           |""".stripMargin
      val boxPlotCommand = plot.BoxPlot.getCommand(workspaceDir.getParentFile, workspaceDir.getName)
      val violinPlotCommand = plot.ViolinPlot.getCommand(workspaceDir.getParentFile, workspaceDir.getName)
      val zScorePlotCommand = plot.ZScore.getCommand(workspaceDir.getParentFile, workspaceDir.getName, convert = false)
      List(produceScCommand) ::: testCommands ::: List(
        fillColorCommand,
        zScorePlotCommand,
        boxPlotCommand,
        violinPlotCommand
      )
    }
    List(CommandData(workspaceDir, commands))
  }

  override def producePlotConfigFile(workspaceDir: File, index: Int): Any = {
    val isMul = Tool.isMulGroup(workspaceDir)
    plot.BoxPlot.initConfigFile(workspaceDir.getParentFile, idStr = workspaceDir.getName)
    plot.ViolinPlot.initConfigFile(workspaceDir.getParentFile, idStr = workspaceDir.getName)
    plot.ZScore.initConfigFile(workspaceDir.getParentFile, idStr = workspaceDir.getName)
    if (!isMul) {
      plot.VolcanoPlot.initConfigFile(workspaceDir.getParentFile, idStr = workspaceDir.getName)
    }
  }

}
